(function($) {
  var prefs = new gadgets.Prefs();
  var key = prefs.getString('apikey');
  var filter = prefs.getString('filter');
  var friend = '';
  var diagramId;
  var diagrams;
  var diagrams_bak;
  var diagramsCount;
  var diagramsPage;
  var diagramsLimit = prefs.getInt('limit');
  var folders;
  var printWindow;

  var loadHtml = '<div class="load"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/load.gif"></div>';
  var loadHtml2 = '<div class="load2"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/load2.gif"></div>';

  function escape(s) {
    return (s == null || s.length == 0) ? s : s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "<br>");
  }

  function showDate(d) {
    return d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate() + ' ' + d.getHours() + ':' + d.getMinutes() + ":" + d.getSeconds();
  }

  function call(url, callback) {
    var params = {}
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
    params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
    makeCachedRequest(url, callback, params, 1);
  }

  function makeCachedRequest(url, callback, params, refreshInterval) {
    var ts = new Date().getTime();
    var sep = "?";
    if (refreshInterval && refreshInterval > 0) {
      ts = Math.floor(ts / (refreshInterval * 1000));
    }
    if (url.indexOf("?") > -1) {
      sep = "&";
    }
    url = [url, sep, "nocache=", ts].join("");
    gadgets.io.makeRequest(url, callback, params);
  }

  function resize() {
    if (gadgets.window) gadgets.window.adjustHeight();
  }

  function isOpensocial() {
    try {
      opensocial;
      return true;
    } catch(e) {
      return false;
    }
  }

  function removePersonAppData() {
    if (isOpensocial()) {
      var req = opensocial.newDataRequest();
      req.add(req.newRemovePersonAppDataRequest('VIEWER', '*'));
      req.send();
    }
  }

  function getDiagrams() {
    call('https://cacoo.com/api/v1/diagrams.json?apiKey=' + key, showDiagrams);
  }

  function showDiagrams(response) {
    diagrams_bak = response.data;
    if (diagrams_bak != null) {
      execFilter();
      writeDiagrams();
      shareDiagrams();
    } else {
      $('#main').html(prefs.getMsg('geterror'));
    }
    resize();
  }

  function shareDiagrams() {
    if (isOpensocial()) {
      var req = opensocial.newDataRequest();
      var result = diagramFilter('public', diagrams_bak).result;
      req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'diagrams', gadgets.json.stringify(result.slice(0, 10))));
      req.send();
    }
  }

  function writeDiagrams() {
    var i;
    var s = '';
    var ms = '';
    if (diagramsCount == 0) {
      ms = '<img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/left_off.png"> <img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/right_off.png">';
      s = prefs.getMsg('nodiagram');
      $('#main').html(s);
      $('#menu_left').html(ms);
    } else {
      if (isPrev()) {
        ms += '<a id="prev" href="javascript:void(0)"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/left_on.png"></a>';
      } else {
        ms += '<img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/left_off.png">';
      }
      ms += ' ';
      if (isNext()) {
        ms += '<a id="next" href="javascript:void(0)"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/right_on.png"></a>';
      } else {
        ms += '<img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/right_off.png">';
      }
      var first = getFirstCount();
      var last = getLastCount();
      s += '<div id="count">' + diagramsPage + '/' + getAllPageCount() + '</div>';
      for(i = first - 1; i < last; i++) {
        var o = diagrams.result[i];
        var securityStr = '';
        if (o.security == 'private') {
          securityStr = '<img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/security.png" title="' + prefs.getMsg('private') + '">';
        }
        var folderStr = '';
        if(o.folderId != null) {
          folderStr = '<a href="https://cacoo.com/diagrams/?conditionType=MY_FOLDER&myFolderId=' + o.folderId + '" target="_blank">' + escape(o.folderName) + '</a><br>';
        }
        var editStr = '';
        if (friend == '') {
          if (o.editing) {
            editStr = '<img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/active.png" title="' + prefs.getMsg('editing') + '">';
          } else {
            editStr = '<img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/offline.png" title="' + showDate(new Date(o.updated)) + '">';
          }
        }
        var deleteBtn = '';
        if (friend == '' && o.own && !o.editing) {
          deleteBtn = '<img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/delete.png" class="link delete" diagramid="' + o.diagramId + '" title="' + prefs.getMsg('delete') + '">';
        }
        var editBtn = '';
        if (friend == '') {
          editBtn = '<a href="https://cacoo.com/diagrams/' + o.diagramId + '/edit" + target="_blank"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/edit.png" title="' + prefs.getMsg('edit') + '"></a>';
        }
        var imgSize = 72;
        var sheetsStr = '';
        var infoWidth = '';
        if (gadgets.views && gadgets.views.getCurrentView().getName().toLowerCase() == 'canvas') {
          imgSize = 128;
          sheetsStr = '<td class="sheets_info"><div id="' + o.diagramId + '_sheets" class="sheets"></div></td>';
          infoWidth = ' width="200px"';
        }
        s += '<div id="' + o.diagramId + '" class="diagram"><table class="diagram_table" width="100%"><tr><td align="center" valign="middle" width="' + (imgSize + 4) + '" height="' + imgSize + '"><a href="' + o.url + '" target="_blank"><img src="' + o.imageUrlForApi + '?apiKey=' + key + '&width=' + imgSize + '&height=' + imgSize + '" title="' + escape(o.title) + '" style="flort: left;"></a></td><td class="diagram_info"' + infoWidth + '"><a href="' + o.url + '" target="_blank" title="' + escape(o.description) + '">' + escape(o.title) + '</a>' + editStr + securityStr + '<br>' + escape(o.owner.nickname) + '<br>' + folderStr + '<span class="command"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/comment.png" class="link comments" diagramid="' + o.diagramId + '" title="' + prefs.getMsg('showcomment') + '"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/chat.png" class="link chat" diagramid="' + o.diagramId + '" title="' + prefs.getMsg('showchat') + '"><a href="https://cacoo-gadget.googlecode.com/svn/trunk/viewer.html#' + o.diagramId + '" + target="CacooViewer"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/viewer.png" title="' + prefs.getMsg('showviewer') + '"></a><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/print.png" class="link print" diagramid="' + o.diagramId + '" title="' + prefs.getMsg('print') + '"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/copy.png" class="link copy" diagramid="' + o.diagramId + '" title="' + prefs.getMsg('copy') + '">' + deleteBtn + editBtn + '</span><br>' + '</td>' + sheetsStr + '</tr></table><div id="' + o.diagramId + '_comments" class="comments"></div></div>';
      }
      $('#main').html(s);
      $('#menu_left').html(ms);
      if (gadgets.views && gadgets.views.getCurrentView().getName().toLowerCase() == 'canvas') {
        for(i = first - 1; i < last; i++) {
          var o = diagrams.result[i];
          getSheets(o.diagramId);
        }
      }
    }
  }

  function getFirstCount() {
    return (((diagramsPage - 1) * diagramsLimit) + 1);
  }

  function getLastCount() {
    var c = diagramsPage * diagramsLimit;
    if (c > diagramsCount) {
      c = diagramsCount;
    }
    return c;
  }

  function getAllPageCount() {
    return Math.ceil(diagramsCount / diagramsLimit);
  }

  function isNext() {
    var c = diagramsPage * diagramsLimit;
    if (c < diagramsCount) {
      return true;
    }
    return false;
  }

  function isPrev() {
    if (diagramsPage > 1) {
      return true;
    }
    return false;
  }

  function execFilter() {
    diagrams = diagramFilter(filter, diagrams_bak);
    diagramsCount = diagrams.result.length;
    diagramsPage = 1;
  }

  function diagramFilter(filter, datas) {
    var ret;
    if (filter == null || filter == '') {
      ret = datas;
    } else {
      var bak_count = datas.result.length;
      var a = new Array();
      var i;
      if (filter == 'editing') {
        for (i = 0; i < bak_count; i++) {
          var o = datas.result[i];
          if (o.editing == true) {
            a.push(o);
          }
        }
      } else if (filter == 'owner') {
        for (i = 0; i < bak_count; i++) {
          var o = datas.result[i];
          if (o.own) {
            a.push(o);
          }
        }
      } else if (filter == 'shared') {
        for (i = 0; i < bak_count; i++) {
          var o = datas.result[i];
          if (!o.own) {
            a.push(o);
          }
        }
      } else if (filter == 'private') {
        for (i = 0; i < bak_count; i++) {
          var o = datas.result[i];
          if (o.security == 'private') {
            a.push(o);
          }
        }
      } else if (filter == 'public') {
        for (i = 0; i < bak_count; i++) {
          var o = datas.result[i];
          if (o.security != 'private') {
            a.push(o);
          }
        }
      } else if (filter.indexOf('folder_') == 0) {
        var name = filter.substring(7);
        for (i = 0; i < bak_count; i++) {
          var o = datas.result[i];
          if (o.folderId == name) {
            a.push(o);
          }
        }
      }
      ret = new Array();
      ret['result'] = a;
    }
    return ret;
  }

  function writeSelecter() {
    var s = '<form action="javascript:void(0);"><select id="filter" name="filter">';
    s += '<option value=""></option>';
    if (friend == '') {
      s += '<option value="owner">' + prefs.getMsg('owner') + '</option>';
    }
    s += '<option value="shared">' + prefs.getMsg('shared') + '</option>';
    if (friend == '') {
      s += '<option value="public">' + prefs.getMsg('public') + '</option>';
      s += '<option value="private">' + prefs.getMsg('private') + '</option>';
      s += '<option value="editing">' + prefs.getMsg('editing') + '</option>';
      var i;
      var count = folders.result.length;
      for (i = 0; i < count; i++) {
        var o = folders.result[i];
        s += '<option value="folder_' + o.folderId + '">' + o.folderName + '</option>';
      }
    }
    s += '</select></form>';
    $('#menu_left2').html(s);
    $('#filter').val(filter).change(function(){
      filter = $(this).val();
      if (friend == '') {
        prefs.set('filter', filter);
      }
      execFilter();
      writeDiagrams();
      resize();
    });
  }

  function getSheets(diagramId) {
    call('https://cacoo.com/api/v1/diagrams/' + diagramId + '.json?apiKey=' + key, showSheets);
  }

  function showSheets(response) {
    var json = response.data;
    if (json != null) {
      var sheets = json.sheets;
      var count = sheets.length;
      var i;
      var s = '';
      for(i = 0; i < count; i++) {
        var o = sheets[i];
        s += '<div class="sheet"><a class="getpng" href="https://cacoo.com/diagrams/' + json.diagramId + '-' + o.uid + '/export?format=png" title="' + prefs.getMsg('getpng') + '" target="_blank"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/png.png"></a><a href="' + o.url + '" target="_blank"><img class="sheet_img" src="' + o.imageUrlForApi + '?apiKey=' + key + '" title="' + escape(o.name) + '" width="72" height="72"></a></div>';
      }
      $('#' + json.diagramId + '_sheets').html(s);
      $('img.sheet_img').tooltip({ 
        delay: 0,
        showURL: false,
        bodyHandler: function() { 
          return $('<img/>').attr('src', this.src).addClass('overlay_img'); 
        } 
      });
    } else {
    }
    resize();
  }

  function getFolders() {
    call('https://cacoo.com/api/v1/folders.json?apiKey=' + key, function(res){folders = res.data; writeSelecter();});
  }

  function getAccount() {
    if (isOpensocial()) {
      call('https://cacoo.com/api/v1/account.json?apiKey=' + key, updateAccount);
    }
  }

  function updateAccount(response) {
    var json = response.data;
    if (json != null) {
      var req = opensocial.newDataRequest();
      req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'account', gadgets.json.stringify(json)));
      req.send();
    } else {
    }
  }

  function getFriends() {
    if (isOpensocial()) {
      var req = opensocial.newDataRequest();
      var viewerFriends = opensocial.newIdSpec({ "userId" : "VIEWER", "groupId" : "FRIENDS" });
      var opt_params = {};
      opt_params[opensocial.DataRequest.PeopleRequestFields.MAX] = 100;
      opt_params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP;
      req.add(req.newFetchPeopleRequest(viewerFriends, opt_params), 'viewerFriends');

      req.add(req.newFetchPersonAppDataRequest(viewerFriends, 'account', opt_params), 'viewerFriendData');

      req.send(showFriends);
    }
  }

  function showFriends(data) {
    var viewerFriends = data.get('viewerFriends').getData();
    var viewerFriendData = data.get('viewerFriendData').getData();

    var s = '<form action="javascript:void(0);"><select id="friend" name="friend">';
    s += '<option value=""></option>';
    var s2 = '';
    viewerFriends.each(function(person) {
      if (person.getId()) {
        var account = gadgets.json.parse(gadgets.util.unescapeString(viewerFriendData[person.getId()].account));
        if (account) {
          s2 += '<option value="' + person.getId() + '">' + person.getDisplayName() + '(' + account.name + ')</option>';
        }
      }
    });
    if (s2 == '') retrun;
    s += s2;
    s += '</select></form>';
    $('#menu_left3').html(s);
    $('#friend').val(filter).change(function(){
      friend = $(this).val();
      $('#menu_left3').hide();
      $('#main').html(loadHtml);
      if (friend != null && friend.length != 0) {
        getFriendData();
      } else {
        getDiagrams();
      }
      filter = '';
      prefs.set('filter', '');
      writeSelecter();
    });
    $('#menu_right').prepend('<a href="javascript:void(0);" class="link friend" title="' + prefs.getMsg('friend') + '"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/friend.png"></a> ');
    $('a.link.friend').click(function(){
      $('#menu_left3').toggle();
    });
  }

  function getFriendData() {
    if (isOpensocial()) {
      var req = opensocial.newDataRequest();
      var viewerFriends = opensocial.newIdSpec({ "userId" : "VIEWER", "groupId" : "FRIENDS" });
      var opt_params = {};
      opt_params[opensocial.DataRequest.PeopleRequestFields.MAX] = 100;
      opt_params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP;
      req.add(req.newFetchPersonAppDataRequest(viewerFriends, 'diagrams', opt_params), 'viewerFriendDiagrams');

      req.send(showFriendData);
    }
  }

  function showFriendData(data) {
    var viewerFriendDiagrams = data.get('viewerFriendDiagrams').getData();

    var diagrams = gadgets.json.parse(gadgets.util.unescapeString(viewerFriendDiagrams[friend].diagrams));
    if (diagrams) {
      diagrams_bak = new Array();
      diagrams_bak['result'] = diagrams;
      execFilter();
      writeDiagrams();
    } else {
      $('#main').html(prefs.getMsg('geterror'));
    }
    resize();
  }

  function getComments(diagramId) {
    call('https://cacoo.com/api/v1/diagrams/' + diagramId + '.json?apiKey=' + key, showComments);
  }

  function showComments(response) {
    var json = response.data;
    if (json != null) {
      var comments = json.comments;
      var count = comments.length;
      var i;
      var s = '<img class="link close" title="' + prefs.getMsg('close') + '" src="https://cacoo-gadget.googlecode.com/svn/trunk/img/comment.png"><br clear="all">';
      if (count == 0) {
        s += prefs.getMsg('nocomment');
      }
      for(i = 0; i < count; i++) {
        var o = comments[i];
        s += '<div class="user_icon"><img src="' + o.user.imageUrl + '" title="' + escape(o.user.nickname) + '"></div><div class="comment">' + escape(o.user.nickname) + '<br>' + escape(o.content) + '</div>';
      }
      $('#' + diagramId + '_comments').html(s);
    } else {
      $('#' + diagramId + '_comments').html(prefs.getMsg('geterror'));
    }
    resize();
  }
 
  function getChat(diagramId) {
    call('https://cacoo.com/api/v1/diagrams/' + diagramId + '/chat/messages.json?apiKey=' + key, showChat);
  }

  function showChat(response) {
    var json = response.data;
    if (json != null) {
      var comments = json.result;
      var count = comments.length;
      var i;
      var s = '<img class="link close" title="' + prefs.getMsg('close') + '" src="https://cacoo-gadget.googlecode.com/svn/trunk/img/chat.png"><br clear="all">';
      if (count == 0) {
        s += prefs.getMsg('nochatcomment');
      }
      for(i = 0; i < count; i++) {
        var o = comments[i];
        s += '<div class="user_icon"><img src="' + o.user.imageUrl + '" title="' + escape(o.user.nickname) + '"></div><div class="comment">' + escape(o.user.nickname) + '<br>' + escape(o.content) + '</div>';
      }
      $('#' + diagramId + '_comments').html(s);
    } else {
      $('#' + diagramId + '_comments').html(prefs.getMsg('geterror'));
    }
    resize();
  }

  function printDiagram(diagramId) {
    printWindow = window.open('', 'CacooPrint');
    call('https://cacoo.com/api/v1/diagrams/' + diagramId + '.json?apiKey=' + key, writePrintPage);
  }

  function writePrintPage(response) {
    var json = response.data;
    if (json != null) {
      
      printWindow.document.title = json.title;
      var sheets = json.sheets;
      var count = sheets.length;
      var i;
      var s = '<h1>' + json.title + '</h1>';
      for(i = 0; i < count; i++) {
        var o = sheets[i];
        if (i != 0) {
          s += '<div style="page-break-before: always;"></div>';
        }
        s += '<div class="sheet">' + escape(o.name) + '<br><img class="sheet_img" src="' + o.imageUrlForApi + '?apiKey=' + key + '" title="' + escape(o.name) + '"></div>';
      }
      $(printWindow.document.body).html(s);
      printWindow.print();
    } else {
      $(printWindow.document.body).html(prefs.getMsg('geterror'));
    }
  }

  function copyDiagram(diagramId) {
    if (confirm(prefs.getMsg('copyconfirm'))) {
      $('#main').html(loadHtml);
      call('https://cacoo.com/api/v1/diagrams/' + diagramId + '/copy.json?apiKey=' + key, writeCopyPage);
    }
  }

  function writeCopyPage(response) {
    var json = response.data;
    if (json != null) {
      if (friend == '') {
        diagrams_bak.result.unshift(json);
        execFilter();
        writeDiagrams();
        resize();
      } else {
        friend = '';
        $('#friend').val('');
        getDiagrams();
      }
    } else {
      $('#main').html(prefs.getMsg('geterror'));
    }
  }

  function deleteDiagram(diagramId) {
    if (confirm(prefs.getMsg('deleteconfirm'))) {
      $('#main').html(loadHtml);
      call('https://cacoo.com/api/v1/diagrams/' + diagramId + '/delete.json?apiKey=' + key, writeDeletePage);
    }
  }

  function writeDeletePage(response) {
    var json = response.data;
    if (json != null) {
      var i;
      var count = diagrams_bak.result.length;
      for(i = 0; i < count; i++) {
        var o = diagrams_bak.result[i];
        if (o.diagramId == diagramId) {
          diagrams_bak.result.splice(i, 1);
          break;
        }
      }
      execFilter();
      writeDiagrams();
      resize();
    } else {
      $('#main').html(prefs.getMsg('geterror'));
    }
  }

  function setHeader() {
    $('#main').before('<div id="menu"><div id="menu_logo"><a href="https://cacoo.com/diagrams/" target="_blank" title="' + prefs.getMsg('diagrams') + '"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/cacoo_icon.png"></a></div><div id="menu_left"></div><div id="menu_left2"></div><div id="menu_left3"></div><div id="menu_right"><a href="https://cacoo.com/diagrams/new" target="_blank" title="' + prefs.getMsg('new') + '"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/new.png"></a> <a href="javascript:void(0);" class="link reload" title="' + prefs.getMsg('reload') + '"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/reload.png"></a></div></div>');
    $('#main').after('<div id="footer"><a href="https://code.google.com/p/cacoo-gadget/" target="_blank">Cacoo OpenSocial Gadget</a></div>');
    getFolders();
    getAccount();
    getFriends();
  }

  $.event.add(window, 'load', function(){
    if (key == null || key == '') {
      $('#main').html('<div class="logo"><a href="https://cacoo.com/" target="_blank"><img src="https://cacoo-gadget.googlecode.com/svn/trunk/img/logo.png" width="142" height="40"></a></div><div class="message">' + prefs.getMsg('noapikey') + '<a href="https://cacoo.com/profile/api" target="_blank">' + prefs.getMsg('here') + '</a>' + prefs.getMsg('getapikeyinfo') + '</div><div class="register"><form action="javascript:void(0);">' + prefs.getMsg('apikeylabel') + ' <input id="apikey" type="text" name="apikey" size="24"><input type="submit" value="' + prefs.getMsg('register') + '"></form></div><div id="footer"><a href="https://code.google.com/p/cacoo-gadget/" target="_blank">Cacoo OpenSocial Gadget</a></div>');
      resize();
      $('form').submit(function(){
        key = $('#apikey').val();
        if (key == '') {
          alert(prefs.getMsg('noapikey'));
          return false;
        }
        prefs.set('apikey', key);
        setHeader();
        $('#main').html(loadHtml);
        getDiagrams();
        return false;
      });
      removePersonAppData();
    } else {
      setHeader();
      getDiagrams();
    }
  });

  $('a.link.reload').live('click', function() {
    $('#main').html(loadHtml);
    getDiagrams();
  });

  $('img.link.comments').live('click', function() {
    diagramId = $(this).attr('diagramid');
    $('#' + diagramId + '_comments').html(loadHtml2);
    resize();
    getComments(diagramId);
  });

  $('img.link.chat').live('click', function() {
    diagramId = $(this).attr('diagramid');
    $('#' + diagramId + '_comments').html(loadHtml2);
    resize();
    getChat(diagramId);
  });

  $('img.link.print').live('click', function() {
    diagramId = $(this).attr('diagramid');
    printDiagram(diagramId);
  });

  $('img.link.copy').live('click', function() {
    diagramId = $(this).attr('diagramid');
    copyDiagram(diagramId);
  });

  $('img.link.delete').live('click', function() {
    diagramId = $(this).attr('diagramid');
    deleteDiagram(diagramId);
  });

  $('img.link.close').live('click', function() {
    $(this).parent().html('');
    resize();
  });

  $('div.diagram').live('mouseover', function() {
    $(this).addClass('select');
  }).live('mouseout', function() {
    $(this).removeClass('select');
  });

  $('a#prev').live('click', function() {
    diagramsPage--;
    writeDiagrams();
    resize();
  });

  $('a#next').live('click', function() {
    diagramsPage++;
    writeDiagrams();
    resize();
  });

})(jQuery)
